""" Base player plugin classes

Example module usage:

from basePlugin import *

class MyPlugin(BasePlugin):

    # default plugin root folder
    @plugin_folder
    def root(self):
        yield PFolder(label='folder 1', call='myFolder')
        yield PFolder(label='folder 2', call='subFolder', param={'id':3})


    # Folder items can be returned in list
    @plugin_folder
    def nyFolder(self):
        return [
                PItem(label='A', call='play', param={'file': 'a.mpg'}),
                PItem(label='B', call='play', param={'file': 'b.mpg'}),
            ]

    # Folder items can be returned as generator with 'yield'
    @plugin_folder
    def subFolder(self, id):
        yield PItem(label='MusicFile', call='play',
                    param={'file': 'my.mp3'}, type='music')

    @plugin_call
    def play(self, file):
        info = PItem(label=file)
        self.xbnc.play(file, info)


"""

__author__ = "Tomas Pokorny (tomas.zemres@gmail.com)"
__version__ = "0.2"
__license__ = "GPL"

from wget import WGet

__all__ = ["BasePlugin", "PItem", "PFolder", "plugin_folder", "plugin_call",
            "CancelOperation"]


class CancelOperation(Exception):
    pass


####################
### Item classes ###
####################

class PItem:
    """ Plugin directory list item

        Attributes:
            label       - item label
            label2      - item label2
            call        - plugin method name to be called
            param       - dictionary with parameters for plugin method
            info        - dictionary with infoLabel
            isFolder    - 1: this item is folder, 0: this item is file
            iconURL     - thumbnail icon image URL
            type        - media type ['video' (default) or 'music' or ...]
            path        - target path / url
            menuItems   - context menu items
    """
    DEFAULT_TYPE = 'video'

    def __init__(self, label, label2=None, call=None, param={}, info={},
                    isFolder=False, iconURL=None, type=None, path=None,
                    menuItems=None):
        """ Constructor """
        self.label      = label
        self.label2     = label2
        self.call       = call
        self.param      = param
        self.info       = info
        self.isFolder   = bool(isFolder)
        self.iconURL    = iconURL
        self.type       = type or self.DEFAULT_TYPE
        self.path       = path
        self.menuItems  = menuItems


    def __repr__(self):
        out = "<%s label=%r" % (self.__class__.__name__, self.label)
        if self.label2 is not None:
            out += " label2="+repr(self.label2)
        out += " call=%r param=%r" % (self.call, self.param)
        out += " info="+repr(self.info)
        if self.isFolder:
            out += " isFolder"
        if self.iconURL is not None:
            out += " iconURL="+repr(self.iconURL)
        if self.path is not None:
            out += " path="+repr(self.path)
        out += " type="+repr(self.type)+'>'
        return out


    def __cmp__(self, other):
        return cmp(repr(self), repr(other))


def PFolder(label, **arg):
    """ PFolder generates PItem with isFolder=1

        see PItem documentation
    """
    arg['isFolder'] = 1
    return PItem(label=label, **arg)



#########################
### Method decorators ###
#########################

def plugin_call(method):
    """ Plugin folder method decorator """
    method.is_plugin_call = 1
    return method


def plugin_folder(method):
    """ Plugin call method decorator """
    def folder_wrapper(self, *arg, **kwarg):
        iter = method(self, *arg, **kwarg)
        if not hasattr(iter, '__call__'):
            iter = (iter or []).__iter__
        for info in iter():
            self.core.addItem(info)
        self.core.endOfList()

    return plugin_call(folder_wrapper)

##################
### Base class ###
##################

class BasePlugin:
    """ Base Player Plugin class """
    LOGPREFIX = ""

    def __init__(self, interface):
        """ Constructor """
        # set interface instance
        self.core = interface
        self.wget = WGet()


    def call(self, *arg, **kwarg):
        """ Base plugin call """
        (callName, params) = self.core.getCallParams(*arg, **kwarg)
        method = getattr(self, callName or 'root', None)

        if getattr(method, 'is_plugin_call', 0):
            try:
                return method(**params)
            except CancelOperation:
                self.core.cancelOperation()
        else:
            raise Exception( "Plugin %s has not plugin_call %r"
                                % (self.__class__.__name__, callName) )


    ### Extended logging methods ###

    def log(self, message, level='INFO'):
        """ Log message """
        self.core.log(self.LOGPREFIX + message, level)

    def debug(self, message):
        """ Log debug message """
        self.log(message, 'DEBUG')

    def warning(self, message):
        """ Log warning """
        self.log(message, 'WARNING')

    def error(self, message):
        self.log(message, 'ERROR')


